package repo

import (
	"errors"
	"fmt"
	"server/common/dto/response"
	"server/core"
	"server/utils"
	"time"

	"github.com/thoas/go-funk"
	"gorm.io/gorm"
)

func (r *Repository[T]) GenericCreateWithData(condition any, data any, flag string, errorHandler func() *response.ServiceError) *response.ServiceError {
	var entity T
	if condition != nil {
		exists, err := r.CheckDataExistsByCondition(condition, flag)
		if err != nil {
			return err
		}
		if exists {
			return errorHandler()
		}
	}
	result := r.DB.Model(&entity).Create(data)
	return core.HandelError(result)
}

func (r *Repository[T]) GenericCreateRelationshipDataWithTransaction(
	tx *gorm.DB,
	entity any,
	condition any,
	errorHandler func() *response.ServiceError,
) *response.ServiceError {
	exists, err := r.CheckDataExistsByCondition(condition, "")
	if err != nil {
		return err
	}
	if exists {
		return errorHandler()
	}
	result := tx.Create(entity)
	if err := core.HandelError(result); err != nil {
		return err
	}
	return nil
}

func (r *Repository[T]) GenericLogicDeleteById(id string, flag string, errorHandler func() *response.ServiceError) (bool, *response.ServiceError) {
	condition := map[string]interface{}{"id": id}
	exists, err := r.CheckDataExistsByCondition(condition, flag)
	if err != nil {
		return false, err
	}
	if !exists {
		return false, errorHandler()
	}
	result := r.DB.Model(new(T)).Where(condition).Updates(map[string]any{
		"is_delete":  true,
		"deleted_at": time.Now().UnixMilli(),
	})
	return true, core.HandelError(result)
}

func (r *Repository[T]) GenericModifyByCondition(id string, condition any, errorHandler func() *response.ServiceError) (bool, *response.ServiceError) {
	entity, err := r.GenericQueryDetailById(id, errorHandler)
	if err != nil {
		return false, err
	}
	result := r.DB.Model(&entity).Where("id = ?", id).Omit("id").Updates(condition)
	if err := core.HandelError(result); err != nil {
		return false, err
	}
	return true, nil
}

func (r *Repository[T]) GenericModifyRelationshipDataWithTransaction(
	tx *gorm.DB,
	entity any,
	condition any,
	errorHandler func() *response.ServiceError,
) *response.ServiceError {
	exists, err := r.CheckDataExistsByCondition(condition, "")
	if err != nil {
		return err
	}
	if exists {
		return errorHandler()
	}
	result := tx.Model(&entity).Where(condition).Updates(entity)
	if err := core.HandelError(result); err != nil {
		return err
	}
	return nil
}

func (r *Repository[T]) GenericQueryListByCondition(orderType, orderBy string, condition map[string]interface{}) ([]T, *response.ServiceError) {
	var entities []T
	for key, value := range condition {
		if funk.IsEmpty(value) {
			delete(condition, key)
		}
		if key == "page" || key == "size" {
			delete(condition, key)
		}
	}
	orderBy = utils.DefaultString(orderBy, "created_at")
	orderType = utils.DefaultString(orderType, "ASC")
	condition["is_delete"] = false
	result := r.DB.Model(new(T)).
		Where(condition).
		Order(fmt.Sprintf("%s %s", orderBy, orderType)).
		Find(&entities)
	if err := core.HandelError(result); err != nil {
		return nil, err
	}
	return entities, nil
}

func (r *Repository[T]) GenericQueryPageByCondition(
	page, size int,
	orderType, orderBy string,
	condition map[string]interface{},
) (*response.PageResponse[string], []T, *response.ServiceError) {
	var entities []T

	// 设置分页和默认查询参数
	page = utils.DefaultInt(page, 1)
	size = utils.DefaultInt(size, 10)
	orderType = utils.DefaultString(orderType, "ASC")
	orderBy = utils.DefaultString(orderBy, "created_at")
	offset := (page - 1) * size

	// 过滤空值条件
	for key, value := range condition {
		if funk.IsEmpty(value) ||
			key == "page" ||
			key == "size" ||
			key == "order_type" ||
			key == "order_by" {
			delete(condition, key)
		}
	}

	// 基础查询过滤 is_delete=false
	baseQuery := r.DB.Model(new(T)).Where("is_delete = ?", false)

	// 查询数量
	var count int64
	countResult := r.DB.
		Model(new(T)).
		Where(map[string]interface{}{
			"is_delete": false,
		}).
		Where(condition).
		Count(&count)
	if err := core.HandelError(countResult); err != nil {
		return &response.PageResponse[string]{Page: page, Size: size, Total: 0}, nil, err
	}

	// 无数据，提前返回
	if count == 0 {
		return &response.PageResponse[string]{Page: page, Size: size, Total: 0}, []T{}, nil
	}

	// 查询数据列表
	result := baseQuery.
		Where(condition).
		Order(fmt.Sprintf("%s %s", orderBy, orderType)).
		Limit(size).
		Offset(offset).
		Find(&entities)

	if err := core.HandelError(result); err != nil {
		return nil, nil, err
	}

	// 构造分页响应
	pageData := &response.PageResponse[string]{
		Page:  page,
		Size:  size,
		Total: count,
	}
	return pageData, entities, core.HandelError(result)
}

func (r *Repository[T]) GenericQueryDetailById(id string, errorHandler func() *response.ServiceError) (T, *response.ServiceError) {
	var entity T
	result := r.DB.Where("is_delete = ?", false).First(&entity, id)
	if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		return entity, errorHandler()
	}
	return entity, core.HandelError(result)
}

func (r *Repository[T]) GenericQueryDetailByContition(condition map[string]interface{}, errorHandler func() *response.ServiceError) (T, *response.ServiceError) {
	var entity T
	result := r.DB.Where(condition).First(&entity)
	if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		return entity, errorHandler()
	}
	return entity, core.HandelError(result)
}
